#ifndef __MEMORY__
#define __MEMORY__
#include "libc/stdint.h"
#include "register.h"

DEFINE_SYS_WRITE(TTBR0_EL1)
DEFINE_SYS_WRITE(TTBR1_EL1)

DEFINE_SYS_READ(MAIR_EL1)
DEFINE_SYS_WRITE(MAIR_EL1)

DEFINE_SYS_READ(ID_AA64MMFR0_EL1)

DEFINE_SYS_WRITE(TCR_EL1)

DEFINE_SYS_READ(SCTLR_EL1)
DEFINE_SYS_WRITE(SCTLR_EL1)

DEFINE_MEMORY_READ(__kernel_end);


#define MM_DEVICE_G_R_E_INDEX 0
#define MM_DEVICE_NG_R_E_INDEX 1
#define MM_DEVICE_NG_NR_E_INDEX 2
#define MM_DEVICE_NG_NR_NE_INDEX 3
#define MM_NORMAL_CACHEABLE_INDEX 4
#define MM_NORMAL_NOCACHEABLE_INDEX 5

#define MM_DEVICE_G_R_E         (0b00001100)
#define MM_DEVICE_NG_R_E        (0b00001000)
#define MM_DEVICE_NG_NR_E       (0b00000100)
#define MM_DEVICE_NG_NR_NE      (0b00000000)
#define MM_NORMAL_CACHEABLE     (0b10100000)
#define MM_NORMAL_NOCACHEABLE   (0b01000000)

#define ASID_8_BIT  (0x0)
#define ASID_16_BIT (0x2)

#define SHAREABLITY_NON_SHAREABLE           (0b00)
#define CACHEABILITY_OUTER_NON_CACHEABLE    (0b00)
#define CACHEABILITY_INNER_NON_CACHEABLE    (0b00)

#define PAGE_TABLE_ENTRY_TYPE_BLOCK     (0b0)
#define PAGE_TABLE_ENTRY_TYPE_TABLE     (0b1)

#define PAGE_TABLE_ENTRY_VALID		(0b1)
#define PAGE_TABLE_ENTRY_INVALID	(0b1)

#define PAGE_4K_OFFSET      (12)
#define GRANULE_SIZE_4KB    (0x1000)


#define MEMORY_START    (0x40000000)
#define MEMORY_END      (0x60000000)
#define MEMORY_SIZE     (0x20000000)


typedef struct memory{
    uint64_t kernel_num;
    uint64_t user_num;
    bool status[0x20000];  // 1 被使用； 0 未被使用
}memory;


typedef union PageTableDescriptor {
	struct {
		uint64_t valid				: 1;
		uint64_t type				: 1;
		uint64_t IGNORED2			: 10;
		uint64_t nextLevelTableAddr	: 36;
		uint64_t RES0				: 3;
		uint64_t IGNORED 			: 8;
		uint64_t PNXTbale			: 1;
		uint64_t XNTable 			: 1;
		uint64_t APTable			: 2;
		uint64_t NSTable			: 1;
	} __attribute__((packed)) reg;
	uint64_t val;
} __attribute__((packed)) PageTableDescriptor;

typedef union PageTableEntry {
    struct {
        uint64_t valid			: 1;
        uint64_t type			: 1;
        uint64_t attrIndx		: 3;
        uint64_t NS				: 1;
        uint64_t AP				: 2;
        uint64_t SH				: 2;
        uint64_t AF				: 1;
        uint64_t nG				: 1;
        uint64_t OA				: 4;
        uint64_t nT				: 1;
        uint64_t RES1			: 13;
        uint64_t outputAddress	: 18;
        uint64_t RES2			: 2;
        uint64_t GP				: 1;
        uint64_t DBM			: 1;
        uint64_t contiguous		: 1;
        uint64_t PXN			: 1;
        uint64_t UXN			: 1;
        uint64_t IGNORE			: 4;
        uint64_t PBHA			: 4;
        uint64_t IGNORE1		: 1;
	} __attribute__((packed)) reg;
	uint64_t val;
} __attribute__((packed)) PageTableEntry;


typedef union MemoryModelFeatureRegisterEl1 {
    struct {
        uint64_t PARange: 4;
        uint64_t ASIDBits: 4;
        uint64_t BigEnd: 4;
        uint64_t SNSMem: 4;
        uint64_t BigEndEL0: 4;
        uint64_t TGran16: 4;
        uint64_t TGran64: 4;
        uint64_t TGran4: 4;

        uint64_t Reverse:32;
	} __attribute__((packed)) reg;
	uint64_t val;
} __attribute__((packed)) MemoryModelFeatureRegisterEl1;

typedef union TranslationControlRegister{
        struct {
            uint64_t T0SZ: 6;
            uint64_t Reserved1: 1;
            uint64_t EPD0: 1;
            uint64_t IRGN0: 2;
            uint64_t ORGN0: 2;
            uint64_t SH0: 2;
            uint64_t TG0: 2;
            uint64_t T1SZ: 6;
            uint64_t A1: 1;
            uint64_t EPD1: 1;
            uint64_t IRGN1: 2;
            uint64_t ORGN1: 2;
            uint64_t SH1: 2;
            uint64_t TG1: 2;
            uint64_t IPS: 3;
            uint64_t Reserved2: 1;
            uint64_t AS: 1;
            uint64_t TBI0: 1;
            uint64_t TBI1: 1;
            uint64_t HA: 1;
            uint64_t HD: 1;
            uint64_t HPD0: 1;
            uint64_t HPD1: 1;
            uint64_t HWU059: 1;
            uint64_t HWU060: 1;
            uint64_t HWU061: 1;
            uint64_t HWU062: 1;
            uint64_t HWU159: 1;
            uint64_t HWU160: 1;
            uint64_t HWU161: 1;
            uint64_t HWU162: 1;
            uint64_t TBID0: 1;
            uint64_t TBID1: 1;
            uint64_t NFD0: 1;
            uint64_t NFD1: 1;
            uint64_t E0PD0: 1;
            uint64_t E0PD1: 1;
            uint64_t TCMA0: 1;
            uint64_t TCMA1: 1;
            uint64_t DS: 1;
            uint64_t Reverse3: 4;
	} __attribute__((packed)) reg;
	uint64_t val;
} __attribute__((packed)) TranslationControlRegister;

static inline void dsb() {
	asm volatile("dsb sy":::"memory");
}

static inline void isb() {
	asm volatile("isb":::"memory");
}


#endif /* __MEMORY__ */